/*
This software is distributed under the Simplified BSD License:

Copyright (c) 2008, Chris Venter <chris.venter@gmail.com>
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, 
are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, 
    	this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright notice, 
    	this list of conditions and the following disclaimer in the documentation 
    	and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 
DAMAGE.
*/
#ifndef GENERIK_EMITTER_H
#define GENERIK_EMITTER_H

/** \file emitter.h
Defines a signal-slot callback system where references of the callback objects
are stored in a generic typeless system.
*/

#include <list>
#include <algorithm>
#include <functional>

#include "threads.h"

namespace generik {

	template <typename DATA>
	struct emitter;

	/// interface to a generic receiver
	/** This provides a wrapping interface to an anonymous receiver, and allows
	a DATA type to be passed to it, without knowing what type the receiver
	itself is.
	*/
	template <typename DATA>
	struct receiver
	{
		/// defines a receiver which accepts DATA as parameter
		//typedef emitter<DATA> EMITTER;
		//std::list<EMITTER*> emitters;

		/// pass a DATA instance to the receiver
		virtual void operator()(const DATA& data_in) = 0;

		/// virtual destructor
		virtual ~receiver() {}
		
	};

	/// the emitter structure
	/** This has a list of receivers. All of these interfaces will be
	passed a DATA structure by using the raise() method.
	interfaces may be de/registered using the dis/connect method
	The emitter does not own the addresses it points to, and does not delete
	them upon its destruction
	*/
	template <typename DATA>
	struct emitter
	{
		/// defines a receiver which accepts DATA as parameter
		typedef receiver<DATA> RECEIVER;
		
		/// mutex which protects the receiver list
		mutex _mutex;
		/// the list of receivers
		std::list<RECEIVER*> receivers;

		/// default constructor
		emitter()
		: _mutex("emitter")
		{}

		/// default destructor
		~emitter()
		{}

		struct raiser
		{
			RECEIVER* receiver;
			DATA data;
			raiser(RECEIVER* r, const DATA& d)
			: receiver(r)
			, data(d)
			{}
			static void* execute(void* object)
			{
				((raiser*)object)->execute();
				return 0;
			}
			void execute()
			{
				receiver->operator()(data);
			}
		};
		
		/** Creates a fire-and-forget thread for each receiver.
		We have to do this because a receiver might want to disconnect from this
		emitter upon receiving a transmission; we are holding a lock on the mutex,
		so a possible deadlock may occur.
		
		This might be exhanged for a different algorithm in future.
		If we lock the mutex, make a local copy of the receivers, 
		unlock the mutex and THEN send messages to all the receivers in the
		local copy, they can go wild locking and unlocking the mutex;
		we don't care anymore.
		More Thought Needed...
		*/
		void raise(const DATA& data_in)
		{
			GENERIK_TRACER;
			THREAD_LOCK(_mutex);
			typename std::list<RECEIVER*>::iterator r = receivers.begin();
			for (; r != receivers.end(); ++r)
			{
				raiser* _raiser = new raiser(*r, data_in);
				pthread_t raisethread;
				pthread_create(&raisethread, 0, raiser::execute, _raiser);
				pthread_detach(raisethread); // not interested in result
			}
		}
		
		/// connects to the receiver
		void connect(RECEIVER* receiver_in)
		{
			//GENERIK_TRACER;
			THREAD_LOCK(_mutex);
			receivers.push_back(receiver_in);
		}

		/// disconnects from the receiver
		void disconnect(RECEIVER* receiver_in)
		{
			//GENERIK_TRACER;
			THREAD_LOCK(_mutex);
			receivers.remove(receiver_in);
		};

	private:

		/// copy constructor
		/** Protected from access. Using this is not allowed, as it would not be sane.
		When a receiver is destroyed, one of its last acts should be to
		disconnect itself from any emitters. Since an emitter-copy will not
		propogate to the receiver, it is dangerous
		*/
		emitter(const emitter& emitter_in)
		{}

	};

}

#endif // GENERIK_EMITTER_H

